package qos.estimator.statistics;

import java.util.HashMap;
import java.util.Map;

import fuzzy.RulesParsingException;

import qos.estimator.exception.CollectorException;
import qos.estimator.fuzzy.ClassificationTuple;
import qos.estimator.fuzzy.RuleGenerator;
import qos.estimator.tpch.TPCHQueryExecutor;

public class SystemStatisticsCollector implements Runnable{
	
	private Map<String, Double> statistics;
	private IStatisticsCollector cpuStatisticsCollector,  memoryStatisticsCollector, 
							     diskStatisticsCollector, databaseStatisticsCollector;
	
	private ClassificationTuple classificationTuple;
	
	public SystemStatisticsCollector() {
		classificationTuple = new ClassificationTuple();
		this.cpuStatisticsCollector = new CPUStatisticsCollector();
		this.memoryStatisticsCollector = new MemoryStatisticsCollector();
		this.diskStatisticsCollector = new DiskStatisticsCollector();
		this.databaseStatisticsCollector = new DatabaseStatisticsCollector();
	}
	
	/**
	 * Starts collecting statistics from the server. The following statistics are
	 * collected: 
	 * <ul>
	 * 	<li>%steal: CPU Steal percentage</li>
	 * 	<li>%nice: CPU Nice percentage</li>
	 * 	<li>%guest: CPU guest percentage</li>
	 * 	<li>%iowait: CPU IOWait percentage</li>
	 * 	<li>%soft: CPU Soft percentage</li>
	 * 	<li>%usr: CPU User percentage</li>
	 * 	<li>intr/s: Number of interruptions per second</li>
	 * 	<li>%sys/s:</li>
	 * 	<li>residentSetSize</li>
	 * 	<li>minorFaultsPerSecond</li>	
	 * 	<li>majorFaultsPerSecond</li>
	 * 	<li>memory</li>
	 * 	<li>diskUsage</li>
	 * 	<li>virtualSize</li>
	 * 	<li>concSessions</li>
	 * 	<li>locks</li>
	 * 	<li>buffers</li>
	 * </ul> 
	 * 
	 * @param withNoise determines if noise should be inserted. If true, a thread will be <br />
	 * instantiated and started, issuing the database TPC-H queries following an exponential distribution. 
	 */
	public void startCollecting(boolean withNoise) {
		//introduces some noise, by issuing tpch queries randomly and
		//according to an exponential distribution.
		if(withNoise){
			new Thread(new TPCHQueryExecutor()).start(); 
		}
		statistics = new HashMap<String, Double>();
		String header = "%steal\tresidentSetSize\t%guest\tmajorFaultsPerSecond\t%iowait\t%soft\t%usr\tmemory\tdiskUsage\tvirtualSize\tminorFaultsPerSecond\tintr/s\t%sys/s\tconcSessions\tlocks\tbuffers\t%nice";
		System.out.println(header);
		while(true){
			try{
				statistics.putAll(cpuStatisticsCollector.next());	
				statistics.putAll(diskStatisticsCollector.next());
				statistics.putAll(memoryStatisticsCollector.next());
				statistics.putAll(databaseStatisticsCollector.next());
				
				if(statistics.size() == 17) {
					classificationTuple.setResidentSetSize(statistics.get("residentSetSize"));
					classificationTuple.setMajorFaultsPerSecond(statistics.get("majorFaultsPerSecond"));
					classificationTuple.setCpuIOWaitPercentual(statistics.get("%iowait"));
					classificationTuple.setCpuSoftPercentual(statistics.get("%soft"));
					classificationTuple.setCpuUsrPercentual(statistics.get("%usr"));
					classificationTuple.setMemoryPercentual(statistics.get("memory"));
					classificationTuple.setDiskUsage(statistics.get("diskUsage"));
					classificationTuple.setVirtualSize(statistics.get("virtualSize"));
					classificationTuple.setMinorFaultsPerSecond(statistics.get("minorFaultsPerSecond"));
					classificationTuple.setInterruptionsPerSecond(statistics.get("intr/s"));
					classificationTuple.setCpuSysPercentual(statistics.get("%sys"));
					classificationTuple.setConcSessions(statistics.get("concSessions"));
					classificationTuple.setBuffers( statistics.get("buffers"));
					classificationTuple.setLocks( statistics.get("locks"));
				}
				Thread.sleep(5000);
			}catch(CollectorException e){
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	

	
	public String getLine(){
		return classificationTuple.getAsLine();
	}
	
	public ClassificationTuple getStatistics(){
		return classificationTuple;
		
	}

	@Override
	public void run() {
		startCollecting(true);		
	}

	
	
	public static void main(String[] args) {
		SystemStatisticsCollector systemStatisticsCollector = new SystemStatisticsCollector();
		systemStatisticsCollector.startCollecting(true);
	}

}
